package com.exrobot.module.rbt.framework.pudu;


import com.alibaba.fastjson.JSONObject;
import com.exrobot.framework.common.util.http.HttpUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

public class Tools {
    private static final String MAC_NAME = "HmacSHA1";
    private static final String ENCODING = "UTF-8";
    private static final  String host = "https://open-platform.pudutech.com/pudu-entry";
    private static final String apiAppKey = "Your apiAppKey";
    private static final String apiAppSecret = "Your apiAppSecret";
    private static final String acceptHeader = "application/json";
    private static final String contentType = "application/json";

    private static JSONObject getHttp(String url,Map<String, String> params) throws Exception {
        url = url + "?" + sortQueryParams(params);
        String xDate = getGMTTime();
        String stringToSign = String.format("x-date: %s\n%s\n%s\n%s\n%s\n%s", xDate, "GET", acceptHeader, contentType, "", url);
        // Encode string with HMAC and base64
        byte[] hmacStr = HmacSHA1Encrypt(stringToSign, apiAppSecret);
        String signature = base64Encode(hmacStr);
        String authHeader = String.format("hmac id=\"%s\", algorithm=\"hmac-sha1\", headers=\"x-date\", signature=\"%s\"", apiAppKey, signature);

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", acceptHeader);
        headers.put("Host", host);
        headers.put("Content-Type", contentType);
        headers.put("x-date", xDate);
        headers.put("Authorization", authHeader);
        String response = HttpUtils.get(url, headers);
        return JSONObject.parseObject(response);
    }

    private static JSONObject postHttp(String url,JSONObject reqBody) throws Exception {
        String bodyJsonStr = reqBody.toJSONString();
        String contentMD5 = base64Encode(getMD5(bodyJsonStr).getBytes());
        String xDate = getGMTTime();
        String stringToSign = String.format("x-date: %s\n%s\n%s\n%s\n%s\n%s", xDate, "POST", acceptHeader, contentType, contentMD5, "");
        // Encode string with HMAC and base64
        byte[] hmacStr = HmacSHA1Encrypt(stringToSign, apiAppSecret);
        String signature = base64Encode(hmacStr);
        String authHeader = String.format("hmac id=\"%s\", algorithm=\"hmac-sha1\", headers=\"x-date\", signature=\"%s\"", apiAppKey, signature);
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", acceptHeader);
        headers.put("Host", host);
        headers.put("Content-Type", contentType);
        headers.put("x-date", xDate);
        headers.put("Authorization", authHeader);
        headers.put("Content-MD5", contentMD5);
        String response = HttpUtils.post(url, headers,bodyJsonStr);
        return JSONObject.parseObject(response);
    }

    private static String getGMTTime(){
        Calendar cd = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sdf.format(cd.getTime());
    }

    private static String sortQueryParams(String queryParam){
        // parameters should be in alphabetical order
        if (queryParam == null || queryParam == ""){
            return "";
        }
        String[] queryParams = queryParam.split("&");
        Map<String, String> queryPairs = new TreeMap<>();
        for(String query: queryParams){
            String[] kv = query.split("=");
            queryPairs.put(kv[0], kv[1]);
        }
        StringBuilder sortedParamsBuilder = new StringBuilder();
        Iterator iter = queryPairs.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry entry = (Map.Entry) iter.next();
            sortedParamsBuilder.append(entry.getKey());
            sortedParamsBuilder.append("=");
            sortedParamsBuilder.append(entry.getValue());
            sortedParamsBuilder.append("&");
        }
        String sortedParams = sortedParamsBuilder.toString();
        sortedParams = sortedParams.substring(0, sortedParams.length() - 1);

        return sortedParams;
    }

    private static String sortQueryParams(Map<String,String> mapParam){
        if (mapParam.isEmpty()){
            return "";
        }
        StringBuilder sortedParamsBuilder = new StringBuilder();
        Iterator iter = mapParam.entrySet().iterator();
        while(iter.hasNext()){
            Map.Entry entry = (Map.Entry) iter.next();
            sortedParamsBuilder.append(entry.getKey());
            sortedParamsBuilder.append("=");
            sortedParamsBuilder.append(entry.getValue());
            sortedParamsBuilder.append("&");
        }
        String sortedParams = sortedParamsBuilder.toString();
        sortedParams = sortedParams.substring(0, sortedParams.length() - 1);

        return sortedParams;
    }

    private static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception {
        byte[] data = encryptKey.getBytes(ENCODING);
        SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
        Mac mac = Mac.getInstance(MAC_NAME);
        mac.init(secretKey);

        byte[] text = encryptText.getBytes(ENCODING);
        return mac.doFinal(text);
    }

    private static String base64Encode(byte[] key) {
        final Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(key);
    }

    private static String getMD5(String str) {
        String md5Hex = DigestUtils.md5Hex(str);
        return md5Hex;
    }

}
